﻿#ifndef ATTROBJ_H
#define ATTROBJ_H

#include "xvobject.h"
#include <mutex>

namespace xvs {

enum EnumVisibleType//属性可见类型
{
    VisibleType_True,//默认显示
    VisibleType_False,//默认不显示(可调整成显示)
    VisibleType_Inner,//内部用(绝不显示)
};

class InstObj;

class AttrObjData;

/**
 * @brief                   属性对象
 * @note                    级别：枝干属性(BranchObj)/叶子属性
 * @property    AttrType    输入(出)类型属性
 * @property    DataType    数据类型(Integer,Real,Bool,String,Enum)
 * @property    Data        数据
 * @property    DefaultData 默认数据
 * @property    LinkData    链接数据
 * @property    Visible     可见类型(默认不可见)
 * @property    OutForceSave    输出强制保存(默认输出属性不保存)
 * @property    LinkExtend  结构体扩展(扩展后子属性可参与链接)
 * @property    LinkFile    保存(加载)时自定义保存内容
 * @note        ------------------------------------------------后面是关于数据取值的属性
 * @property    Min         数据为Integer/Real时的最小值
 * @property    Max         数据为Integer/Real时的最大值
 * @property    Decimals    数据为Real时小数点后有几位
 * @property    Step        数据为Integer/Real时每次递增(减)的幅度
 */
class OBJLIB_EXPORT AttrObj : public XVObject
{
    Q_OBJECT
public:
    AttrObj();
    ~AttrObj();

//    void CloneAttrObj(AttrObj *copyObj);

public:
    QJsonObject Save(const QString& path);
    void Load(QJsonObject &json, const QString &path);//path 工程路径

    /**
     * @brief AutoCreate    根据数据结构创建子属性对象
     */
    void AutoCreate();
    InstObj* InstObj();//属性对象 所属 的 指令对象
    void SetInstObj(class InstObj* instobj);

    AttrObj* BranchObj();//获取枝干属性对象
    bool IsBranchObj();//是否枝干属性对象

    AttrObj* AddAttrObj(const QString& name);//根据名称添加属性对象
    AttrObj* AddAttrObj(const QString& name, QVariant data);

    int ChildCount() const//子属性对象个数
    {
        return this->Count();
    }

    AttrObj* ChildAt(const int index)//访问子属性对象
    {
        XVObject* obj = this->At(index);
        if (obj == nullptr)
            return nullptr;
        if (obj->ObjType() == ObjType_Attr)
        {
            return qobject_cast<AttrObj*>(obj);
        }
        return nullptr;
    }

public://属性相关
    QString DataType();

    QVariant Data(bool linkdata = true);//linkdata=false代表取属性对象的Data,linkdata=true则代表可能会取到链接的属性元素;
    void SetData(QVariant data);

    QVariant DefaultData();
    void SetDefaultData(const QVariant &data);

    EnumAttrType AttrType() const;
    void SetAttrType(EnumAttrType type);

    EnumVisibleType Visible() const;
    void SetVisible(const EnumVisibleType visible);

    bool OutForceSave() const;
    void SetOutForceSave(const bool outSave);

    bool CanSetDataExtend();
    bool DataExtend();
    void SetDataExtend(const bool extend);

    QString LinkFile();
    void SetLinkFile(const QString& file);

    QString Min() const;
    void SetMin(const QString& min);

    QString Max() const;
    void SetMax(const QString& max);

    int Decimals() const;
    void SetDecimals(const int value);

    QString Step();
    void SetStep(const QString& step);

public://链接
    bool ContainLinkObj(AttrObj* linkobj);//当前属性的链接列表是否存在传入的linkobj,存在=true;不存在=false;

    QList<AttrObj*> LinkObjList();//获取和当前属性对象 链接 的属性对象列表

    void AddLinkObj(AttrObj* linkobj);//添加链接 (为空则移除链接; 不为空则添加链接)

    bool CanLink();//可以被链接，但是不一定有链接 最终链接状态要和linkInfos()配合使用

    QList<QPair<class InstObj*, AttrObj*>> LinkInfos();//获取可链接信息

signals:
    void Signal_DataChanged();

private:
    void CycleAttrObjLink(QString srcDataType, AttrObj* attrobj,QList<QPair<class InstObj*,AttrObj*>> &list);

private:
    AttrObjData* d_ptr;

    std::mutex mutex;
};



}

#endif // ATTROBJ_H
